﻿#ifndef TL_VECTOR_H
#define TL_VECTOR_H

#include <iostream>
#include "TL_Status.h"


/*
КОДЫ ОШИБОК:
1 - неизвестная ошибка
2 - недопустимый индекс
*/


namespace TL {
    /* TL::Vector */

    template<class T> class Vector {
    private:
        T *m_Vector;
        unsigned int m_Size;

    private:
        void SetNull();

    public:
        Vector();
        Vector(const Vector<T> &vector);
        ~Vector();

    public:
        void Add(unsigned int newPos, T newValue, TL::Status *status);
        T Get(unsigned int pos, TL::Status *status) const;
        void Remove(unsigned int remPos, TL::Status *status);
        void Set(unsigned int pos, T newValue, TL::Status *status);
        unsigned int Size() const;

    public:
        Vector<T> operator=(Vector<T> &vector);
        T operator[](unsigned int pos);

    public:
        template<class T> friend std::ostream &operator<<(std::ostream &stream, Vector<T> &vector);
    };

    template<class T> void Vector<T>::SetNull()
    {
        m_Vector = 0;
        m_Size = 0;
    }

    template<class T> Vector<T>::Vector()
    {
        SetNull();
    }

    template<class T> Vector<T>::Vector(const Vector<T> &vector)
    {
        if(!vector.m_Size) {
            SetNull();
        } else {
            m_Vector = new T [vector.m_Size];
            
            for(unsigned int i = 0; i < vector.m_Size; i++)
                m_Vector[i] = vector.m_Vector[i];

            m_Size = vector.m_Size;
        }
    }

    template<class T> Vector<T>::~Vector()
    {
        if(m_Size) {
            delete [] m_Vector;
        }
    }

    template<class T> void Vector<T>::Add(unsigned int newPos, T newValue, TL::Status *status)
    {
        status->SetNull();

        if(newPos > m_Size) {
            status->SetError(2);
            return;
        }

        if(m_Size) {
            T *newVector;
            unsigned int i;

            newVector = new T [m_Size+1];

            for(i = 0; i < newPos; i++) {
                newVector[i] = m_Vector[i];
            }

            newVector[newPos] = newValue;

            for(i = newPos+1; i < (m_Size+1); i++) {
                newVector[i] = m_Vector[i-1];
            }

            delete [] m_Vector;
            m_Vector = newVector;
        } else {
            m_Vector = new T [1];
            m_Vector[0] = newValue;
        }

        m_Size++;

        status->SetSuccess();
    }

    template<class T> T Vector<T>::Get(unsigned int pos, TL::Status *status) const
    {
        status->SetNull();

        if(pos >= m_Size) {
            status->SetError(2);
            return 0;
        }
    
        status->SetSuccess();

        return m_Vector[pos];
    }

    template<class T> void Vector<T>::Remove(unsigned int remPos, TL::Status *status)
    {
        status->SetNull();

        if(remPos >= m_Size) {
            status->SetError(2);
            return;
        }
   
        if(m_Size > 1) {
            T *newVector;
            unsigned int i;
        
            newVector = new T [m_Size-1];

            for(i = 0; i < remPos; i++) {
                newVector[i] = m_Vector[i];
            }

            for(i = remPos+1; i < m_Size; i++) {
                newVector[i-1] = m_Vector[i];
            }

            delete [] m_Vector;
            m_Vector = newVector;

            m_Size--;
        } else {
            delete [] m_Vector;

            SetNull();
        }

        status->SetSuccess();
    }

    template<class T> void Vector<T>::Set(unsigned int pos, T newValue, TL::Status *status)
    {
        status->SetNull();

        if(pos >= m_Size) {
            status->SetError(2);
            return;
        }

        m_Vector[pos] = newValue;

        status->SetSuccess();
    }

    template<class T> unsigned int Vector<T>::Size() const
    {
        return m_Size;
    }

    template<class T> Vector<T> Vector<T>::operator=(Vector<T> &vector)
    {
        if(this->m_Size != vector.m_Size) {
            delete [] this->m_Vector;

            this->m_Vector = new T [vector.m_Size];
            this->m_Size = vector.m_Size;
        }

        for(unsigned int i = 0; i < vector.m_Size; i++)
            this->m_Vector[i] = vector.m_Vector[i];

        return *this;
    }

    template<class T> T Vector<T>::operator[](unsigned int pos)
    {
        if(pos >= m_Size) {
            return 0;
        }

        return m_Vector[pos];
    }

    template<class T> std::ostream &operator<<(std::ostream &stream, Vector<T> &vector)
    {
        unsigned int i;
    
        for(i = 0; i < vector.m_Size; i++) {
            stream << vector[i] << " ";
        }

        if(i) {
            stream << "\b"; // затираем последний пробел
        }

        return stream;
    }
}

#endif